package com.commons.service.service.impl;

import cn.hutool.core.util.*;
import com.alibaba.excel.*;
import com.alibaba.excel.converters.longconverter.*;
import com.alibaba.excel.read.builder.*;
import com.alibaba.excel.write.style.column.*;
import com.baomidou.mybatisplus.extension.service.impl.*;
import com.commons.service.dto.*;
import com.commons.service.entity.*;
import com.commons.service.mapper.*;
import com.commons.service.service.*;
import com.commons.tools.utils.*;
import com.google.common.io.Files;
import com.sun.deploy.net.*;
import org.apache.commons.lang3.*;
import org.springframework.http.*;
import org.springframework.stereotype.*;
import org.springframework.web.multipart.*;

import javax.servlet.http.*;
import java.io.*;

import java.nio.file.*;
import java.util.*;

import static com.commons.tools.utils.FileLoadUtil.NO_EXIST_FILE;

@Service
public class FileServiceImpl extends ServiceImpl<AiFileMapper, AiFile> implements FileService {

    @Override
    public String uploadFile(MultipartFile file) {
        try {
            //文件大小验证
            long limitSize = FileLoadUtil.fileSize * FileLoadUtil.FILE_UNIT;
            if (limitSize < file.getSize()) {
                throw new Exception("上传失败，文件大小超出" + FileLoadUtil.fileSize + "M");
            }

            //文件类型验证
            String fileName = file.getOriginalFilename();
            if (StringUtils.isBlank(fileName)) {
                throw new Exception("上传失败，文件名称为空");
            }

            //附件后缀
            String fileExtension = Files.getFileExtension(fileName).toLowerCase(Locale.ROOT);
            if (!FileLoadUtil.fileType.toUpperCase(Locale.ROOT).contains(fileExtension.toUpperCase(Locale.ROOT))) {
                throw new Exception("上传失败，不支持的文件类型");
            }

            //上传路径
            Long id = IdUtil.getSnowflakeNextId();
            Path filePath = Paths.get(FileLoadUtil.getUploadPath() + id + '.' + fileExtension);
            //写入文件
            java.nio.file.Files.write(filePath, file.getBytes());
            //文件数据保存
            String relaFilePath = filePath.toString().replace(Paths.get(FileLoadUtil.fileDir).toString(), "");
            //文件对象
            AiFile aiFile = new AiFile();
            aiFile.setName(fileName);
            aiFile.setPath(relaFilePath);
            aiFile.setSize(file.getSize());
            aiFile.setType(fileExtension);
            aiFile.setId(id);

            //保存附件
            save(aiFile);
            return relaFilePath;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<String> multipleFilesUpload(MultipartFile[] files) {

        List<String> list = new ArrayList<>();
        //循环files
        for (MultipartFile file : files) {
            String commonFileVo = uploadFile(file);
            list.add(commonFileVo);
        }
        return list;
    }

    @Override
    public void downloadFile(long fileId, HttpServletRequest request, HttpServletResponse response) {
        try {
            //查询附件
            AiFile aiFile = this.getById(fileId);
            if (Objects.isNull(aiFile)) {
                throw new Exception(NO_EXIST_FILE);
            }
            //附件路径
            String filePath = FileLoadUtil.getUploadPath() + aiFile.getPath();
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            //文件名重新编码
            String realFileName = FileLoadUtil.setFileDownloadHeader(request, aiFile.getName());
            FileLoadUtil.setAttachmentResponseHeader(response, realFileName);
            FileLoadUtil.writeBytes(filePath, response);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public boolean deleteFile(long id) {
        try {
            //查询附件
            AiFile aiFile = this.getById(id);
            if (Objects.isNull(aiFile)) {
                log.error("文件不存在");
            }
            //附件路径
            String filePath = FileLoadUtil.getDownPath() + aiFile.getPath();

            Path path = Paths.get(filePath);
            boolean pathExists = path.toFile().exists();
            //判断文件夹是否存在
            if (pathExists) {
                java.nio.file.Files.delete(path);
            }
        } catch (IOException e) {
            log.error("文件删除异常", e);
        }
        return this.removeById(id);
    }

    /**
     * 导出excel
     * @param response
     * @param pageDto
     */
    @Override
    public void exportTableAsExcel(HttpServletResponse response,PageDto pageDto) {
        try {
            //1.查询要导出的数据
            List<AiFile> list = this.list();

            // 2.下载EXCEL
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("用户数据", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), Application.class)
                    .registerConverter(new LongStringConverter())
                    //样式的处理类 需要就注册进来.registerWriteHandler(new ExcelTemplateHandler())
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .sheet("数据导出")
                    .doWrite(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void readExcel(MultipartFile file){
        try {
            ExcelListenerUtils deviceListener = new ExcelListenerUtils();
            EasyExcelFactory.read(file.getInputStream(), deviceListener).sheet().doRead();

            Map<Integer, String> headTitleMap = deviceListener.getHeadTitleMap();

            List<Map<Integer, Map<Integer, String>>> list = deviceListener.getList();

            // 遍历数据，写入数据库
            for (int i = 0; i < list.size(); i++) {
                Map<Integer, Map<Integer, String>> innerMap = list.get(i);
                for (Integer key : innerMap.keySet()) {
                    //解析转化成模型
                    AiFile aiFile = new AiFile();
                    this.save(aiFile);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }



}
